﻿using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using Lync.Widget.Library.Configuration;
using Lync.Widget.Library.Presentation.Entities;
using Lync.Widget.Library.Repositories;

namespace Lync.Widget.Library.Presentation.Models
{
    public class GroupsModel : IGroupsModel
    {
        const string GroupsConfigurationPath = @"\Configuration\Adgroups.config";
        private readonly IActiveDirectoryRepository m_ActiveDirectoryRepository;

        public GroupsModel()
            : this(new ActiveDirectoryCachedRepository())
        {
        }

        public GroupsModel(IActiveDirectoryRepository activeDirectoryRepository)
        {
            m_ActiveDirectoryRepository = activeDirectoryRepository;
        }

        public IList<IGroup> GetGroupsAndMembers(string organisationUnit)
        {
            IList<IGroup> result = null;

            var groups = m_ActiveDirectoryRepository.GetGroups(organisationUnit);

            if (groups != null)
            {
                result = groups.Select(group => new Group
                                                  {
                                                      Id = group.Name.Trim().ToLower().Replace(" ", ""),
                                                      Name = group.Name,
                                                      DistinguishedName = group.DistinguishedName,
                                                      Members = m_ActiveDirectoryRepository.GetUsersFromGroup(group)
                                                                                           .Select(member => new GroupMember { Sip = member.SipAddress })
                                                                                           .Cast<IGroupMember>().ToList()
                                                  })
                             .Cast<IGroup>()
                             .ToList();
            }

            return result;
        }

        public IList<IGroupMember> GetGroupMembers(string organisationUnit, string groupName)
        {
            IList<IGroupMember> result = null;

            var groups = m_ActiveDirectoryRepository.GetGroups(organisationUnit);

            var group = groups.SingleOrDefault(gr => gr.DistinguishedName == groupName);

            var groupMembers = m_ActiveDirectoryRepository.GetUsersFromGroup(group);

            if (groupMembers != null)
            {
                result = groupMembers.Select(member => new GroupMember
                                            {
                                                Sip = member.SipAddress,
                                            })
                                   .Cast<IGroupMember>()
                                   .ToList();
            }

            return result;
        }

        public void SaveConfiguration(IGroupConfig config)
        {
            var groupsElement = new XElement("Groups");

            foreach (var group in config.Groups)
            {
                groupsElement.Add(new XElement("Group",
                                            new XElement("Members", group.Members.OrderBy(m => m.Priority).Select(member =>
                                                            new XElement("Member",
                                                            new XAttribute("sip", member.Sip),
                                                            new XAttribute("priority", member.Priority)))),
                                            new XAttribute("id", group.Id),
                                            new XAttribute("name", group.Name),
                                            new XAttribute("distinguishedname", group.DistinguishedName),
                                            new XAttribute("timetowait", group.HuntGroupSettings.TimeToWait),
                                            new XAttribute("huntgroupquantity", group.HuntGroupSettings.UserCount)));

            }

            var root = new XElement("activedirectoryGroups", new XAttribute("root", config.Root), 
                                                             new XAttribute("timetowait", config.TimeToWait),
                                                             new XAttribute("huntgroupquantity", config.HuntgroupQuantity), groupsElement);

            root.Save(HttpContext.Current.Server.MapPath(GroupsConfigurationPath));
        }

        public string GetActiveDirectoryRootFromConfiguration()
        {
            return ConfigurationManager.AppSettings["ActiveDirectoryRoot"];
        }

        public XElement GetConfigurationXml()
        {
            var path = HttpContext.Current.Server.MapPath(GroupsConfigurationPath);
            return File.Exists(path) ? XElement.Load(path) : null;
        }

        public IGroupConfig LoadConfiguration()
        {
            if (GetConfigurationXml() == null) return null;

            var configurationSection = ActiveDirectoryGroupConfigurationSection.Load();

            var groups = configurationSection.Groups.Select(group => new Group
                                                          {
                                                              Name = group.Name,
                                                              DistinguishedName = group.DistinguishedName,
                                                              Id = group.Id,
                                                              HuntGroupSettings = new HuntGroupSetting
                                                                                      {
                                                                                          TimeToWait = group.TimeToWaitInSeconds,
                                                                                          UserCount = group.HuntgroupQuantity,
                                                                                      },
                                                              Members = group.Members
                                                                             .Select(member => new GroupMember
                                                                                                   {
                                                                                                       Priority = member.Priority, 
                                                                                                       Sip = member.Sip,
                                                                                                   })
                                                                             .Cast<IGroupMember>().ToList(),
                                                          }).Cast<IGroup>().ToList();

            return new GroupConfig
                       {
                           Root = configurationSection.Root,
                           HuntgroupQuantity = configurationSection.HuntgroupQuantity,
                           TimeToWait = configurationSection.TimeToWait,
                           Groups = groups,
                       };
        }
    }
}